Моментальные оповещение для Vii Engine 3.0 написан по технологии SSE(Server-Sent Events)

SSE наиболее часто относится к одной из двух областей: Server-Sent Events (технология веб-разработки для односторонней передачи данных от сервера к клиенту в реальном времени) или Streaming SIMD Extensions (набор инструкций процессора Intel для ускорения вычислений). Также в кибербезопасности используется Security Service Edge.

Пример JS

if ('EventSource' in window) {

    const source = new EventSource('/index.php?go=updates_sse');

    source.addEventListener('update', (e) => {
        const d = JSON.parse(e.data);

        if (!d.status) return; // нет новых событий

        // Используем старый метод render
        Updates.render(d);
    });

    source.addEventListener('error', (e) => {
        console.error('SSE error', e);
        // EventSource автоматически переподключается
    });

} else {
    console.warn('Ваш браузер не поддерживает SSE. Включен fallback на long polling.');
    Updates.init(); // fallback на long polling
}


// HTML5 NOTIFICATION
if ('Notification' in window && Notification.permission === 'default') {
    Notification.requestPermission();
}

function sendNotification(title, options = {}) {
    if (!('Notification' in window)) {
        alert('Ваш браузер не поддерживает оповещения');
        return;
    }

    if (Notification.permission === 'granted') {
        const notification = new Notification(title, options);

        notification.onclick = () => {
            console.log('Юзверь кликнул на уведомление.');
        };

        return;
    }

    if (Notification.permission !== 'denied') {
        Notification.requestPermission().then(permission => {
            if (permission === 'granted') {
                new Notification(title, options);
            } else {
                console.log('Юзверь запретил уведомления.');
            }
        });
    }
}

const Updates = {

    timer: null,
    working: false,

    init() {
        if ('Notification' in window && Notification.permission === 'default') {
            Notification.requestPermission();
        }

        this.timer = setInterval(() => this.check(), 3000);
    },

    check() {
        if (this.working) return;

        this.working = true;

        $.post('/index.php?go=updates', res => {

            if (!res?.status) {
                this.working = false;
                return;
            }

            this.render(res);
            this.working = false;

        }, 'json').fail(() => {
            this.working = false;
        });
    },

    render(d) {
        const title = this.getTitle(d.type);

        if (d.type === 8) {
            this.updateMessages(d.link);
        }

        const html = this.buildHtml(d, title);
        $('#updates').append(html);

        this.notify(d, title);
        this.sound();
        this.resize();
    },

    getTitle(type) {
        const titles = {
            1: lang_23,
            2: lang_24,
            3: lang_25,
            4: lang_26,
            5: lang_27,
            6: lang_28,
            7: lang_29,
            8: lang_30,
            9: lang_31,
            10: lang_32,
            11: lang_33,
            12: lang_34,
            13: lang_35
        };

        return titles[type] ?? lang_36;
    },

    updateMessages() {
        if (location.pathname.includes('messages')) return;

        const el = $('#new_msg');
        const current = parseInt(el.text().replace(/\D/g, ''), 10) || 0;
        const cnt = current + 1;

        el.html(`<div class="headm_newac" style="margin-left:37px">${cnt}</div>`);
    },

    buildHtml(d, title) {
        return `
        <div class="update_box cursor_pointer" id="event${d.id}"
            onclick="GoPage(event, '${d.link}'); upClose(${d.id})">
            <div class="update_box_margin">
                <div style="height:19px">
                    <span>${title}</span>
                    <div class="update_close fl_r" onmousedown="upClose(${d.id})">
                        <div class="update_close_ic"></div>
                    </div>
                </div>
                <div class="clear"></div>
                <div class="update_inpad">
                    <a href="/u${d.from_user}" onclick="Page.Go(this.href); return false">
                        <div class="update_box_marginimg">
                            <img src="${d.avatar}" alt="">
                        </div>
                    </a>
                    <div class="update_data">
                        <a href="/u${d.from_user}" onclick="Page.Go(this.href); return false">
                            ${d.username}
                        </a>
                        &nbsp;&nbsp;${d.text}
                    </div>
                </div>
                <div class="clear"></div>
            </div>
        </div>`;
    },

    notify(d, title) {
        if (!('Notification' in window)) return;
        if (Notification.permission !== 'granted') return;

        new Notification(title, {
            body: d.text,
            icon: d.avatar
        });
    },

    sound() {
        const snd = document.getElementById('beep-three');
        snd?.play();
    },

    resize() {
        const boxes = $('.update_box');
        const cnt = boxes.length;

        if (cnt <= 5) {
            $('#updates').animate({ height: `${cnt * 123}px` });
        }

        if (cnt > 5) {
            const first = boxes.first();
            first.animate({ marginTop: '-123px' }, 400, () => {
                first.remove();
            });
        }
    }
};

Пример PHP

/*
    Author: Yuri Balazh
    Engine: PHPSocial Engine
    Copyright: PHPSocial Group (с) 2026
    e-mail: admin@phpsocial.com.ua
    URL: https://vii.phpsocial.com.ua/
    This code is protected by copyright.
*/
if (!defined('MOZG')) die('Hacking attempt!');

NoAjaxQuery();

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no'); // для Nginx

set_time_limit(0);

if (!$logged || empty($user_info['user_id'])) {
    echo "event: error\n";
    echo "dаta: {\"message\":\"Not logged in\"}\n\n";
    flush();
    exit;
}

$userId = (int)$user_info['user_id'];
$maxWait = 30;      // максимум ожидания одного соединения
$interval = 1;      // проверка новых событий каждые 1 сек
$startTime = time();

while ((time() - $startTime) < $maxWait) {

    // Берем только одно новое событие
    $row = $db->super_query("
        SELECT id, type, from_user_id, text, lnk, user_search_pref, user_photo
        FROM `" . PREFIX . "_updates`
        WHERE for_user_id = '{$userId}'
        ORDER BY date ASC
        LIMIT 1
    ");

    if ($row) {
        $fromUserId = (int)$row['from_user_id'];
        $userPhoto  = $row['user_photo'] ?? '';

        $avatar = $userPhoto
            ? "/uploads/users/{$fromUserId}/50_{$userPhoto}"
            : "/templates/Default/images/no_ava_50.png";

        $response = [
            'status'    => true,
            'id'        => (int)$row['id'],
            'type'      => (int)$row['type'],
            'from_user' => $fromUserId,
            'username'  => stripslashes($row['user_search_pref'] ?? ''),
            'text'      => stripslashes($row['text'] ?? ''),
            'avatar'    => $avatar,
            'link'      => $row['lnk'] ?? '',
            'time'      => time(),
        ];

        // Удаляем обработанное событие
        $db->query("DELETE FROM `" . PREFIX . "_updates` WHERE id = '" . (int)$row['id'] . "'");

        echo "event: update\n";
        echo 'dаta: ' . json_encode($response, JSON_UNESCAPED_UNICODE) . "\n\n";
        flush();
        exit; // закончили соединение после события
    }

    // Keep-alive каждые 10 секунд, чтобы соединение не обрывалось
    if ((time() - $startTime) % 10 === 0) {
        echo ":\n\n";
        flush();
    }

    sleep($interval);
}

// Если нет новых событий, отправляем пустой объект
echo "event: update\n";
echo 'dаta: {"status":false}' . "\n\n";
flush();
exit;

Обсуждение новости
Guests, оставишь комментарий?
Имя:*
E-Mail:


Подписаться на комментарии
Статистика
1 посетитель на сайте. Из них:
Гости1
Список пользователей
Test Был(a) в сети 10 часов назад
Комментарии
Информация
Актуальная версия Vii Engine 3.0
Реклама